package me.sealer.exercise;

import java.util.Scanner;

/**
 * @author sealer
 * @date 2018/07/26.
 * @email 1178884049@qq.com
 * 问题描述：
 * 输入
 * 第一行是一个整数 N (1 <= N <= 100, 000) ，表示一共有 N 天。第二行是 N 个被空格分开的整数，表示每天该股票的价格。该股票每天的价格的绝对值均不会超过 1,000,000 。
 * 输出
 * 输出一行。该行包含一个整数，表示能够获得的最大的利润。
 * ===============
 * 样例输入
 * 7
 * 5 14 -2 4 9 3 17
 * 样例输出
 * 34
 * ===============
 * 或：
 *  * 样例输入
 *  * 6
 *  * 6 8 7 4 1 -2
 * 样例输出
 * 2
 * ===============
 * 或：
 *  * 样例输入
 *  * 4
 *  * 18 9 5 2
 * 0
 * ===============
 * 提示
 * 对于第一组样例，可以第 1 次在第 1 天买入（价格为 5 ），然后在第 2 天卖出（价格为 14 ）。第 2 次在第 3 天买入（价格为 -2 ），然后在第 5 天卖出（价格为 11 ）。第 3 次在第 6 天买入（价格为 3 ），然后在第 7 天卖出（价格为 17 ）。一共获得的利润是 (14 - 5) + (9 - (-2)) + (17 - 3) = 34
 * 对于第二组样例，可以第 1 次在第 1 天买入（价格为 6 ），然后在第 2 天卖出（价格为 8 ）。第 2 次仍然在第 2 天买入，然后在第 2 天卖出。一共获得的利润是 8 - 6 = 2
 * 对于第三组样例，由于价格一直在下跌，可以随便选择一天买入之后迅速卖出。获得的最大利润为 0
 */
public class StockTrade {

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        while (true) {
            // 交易价格个数
            System.out.print("请输入数组元素个数：\t");
            int pricesNum = in.nextInt();

            // 价格们
            int[] prices = new int[pricesNum];
            for (int i = 0; i < pricesNum; i++) {
                System.out.print("该数组的长度为" + prices.length + "，请输入下标为" + i + "的元素值: ");
                prices[i] = in.nextInt();
            }

            int profit = calculateProfit(prices);
            System.out.println("此次交易所得利润是： " + profit);
        }

    }

    /**
     * 计算股票的最大利润
     *
     * @param stockDayPrices 股票价格们
     * @return 最大利润
     */
    public static int calculateProfit(int[] stockDayPrices) {
        int profitSum = 0;
        int buyIndex = relativeLowest(stockDayPrices, 0);

        while (buyIndex < stockDayPrices.length - 1) {
            int sellIndex = relativeHighest(stockDayPrices, buyIndex + 1);
            int profit = stockDayPrices[sellIndex] - stockDayPrices[buyIndex];
            profitSum += profit;
            buyIndex = relativeLowest(stockDayPrices, sellIndex == stockDayPrices.length - 1 ? sellIndex : sellIndex + 1);
        }

        return profitSum;
    }

    /**
     * 计算相对最低点， 即买入点
     *
     * @param array 价格数组
     * @param start 开始下标
     * @return 最低点下标
     */
    public static int relativeLowest(int[] array, final int start) {
        int i = start;
        for (; i < array.length - 1; i++) {
            if (array[i] < array[i + 1]) {
                break; // 满足条件， 退出循环
            }
        }
        return i;
    }

    /**
     * 计算相对最低点， 即卖出点
     *
     * @param array 价格数组
     * @param start 开始下标
     * @return 最高点下标
     */
    public static int relativeHighest(int[] array, int start) {
        int i = start;
        for (; i < array.length - 1; i++) {
            if (array[i] > array[i + 1]) {
                break; // 满足条件， 退出循环
            }
        }
        return i;
    }
}
